home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / gsstate.c < prev    next >
C/C++ Source or Header  |  1997-04-25  |  30KB  |  910 lines

  1. /* Copyright (C) 1989, 1995, 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gsstate.c */
  20. /* Miscellaneous graphics state operators for Ghostscript library */
  21. #include "gx.h"
  22. #include "memory_.h"
  23. #include "gserrors.h"
  24. #include "gsstruct.h"
  25. #include "gsutil.h"        /* for gs_next_ids */
  26. #include "gzstate.h"
  27. #include "gxcspace.h"        /* here for gscolor2.h */
  28. #include "gscolor2.h"
  29. #include "gscoord.h"        /* for gs_initmatrix */
  30. #include "gscie.h"
  31. #include "gxcmap.h"
  32. #include "gxdevice.h"
  33. #include "gxpcache.h"
  34. #include "gzht.h"
  35. #include "gzline.h"
  36. #include "gspath.h"
  37. #include "gzpath.h"
  38. #include "gzcpath.h"
  39.  
  40. /* Imported values */
  41. /* The following should include a 'const', but for some reason */
  42. /* the Watcom compiler won't accept it, even though it happily accepts */
  43. /* the same construct everywhere else. */
  44. extern /*const*/ gx_color_map_procs *cmap_procs_default;
  45.  
  46. /* Forward references */
  47. private gs_state *gstate_alloc(P2(gs_memory_t *, client_name_t));
  48. private void gstate_set_contents(P2(gs_state *, gs_state_contents *));
  49. private gs_state *gstate_clone(P4(gs_state *, gs_memory_t *, client_name_t,
  50.                   gs_state_copy_reason_t));
  51. private void gstate_free_contents(P1(gs_state *));
  52. private void gstate_share_paths(P1(const gs_state *));
  53. private int gstate_copy(P4(gs_state *, const gs_state *,
  54.                gs_state_copy_reason_t, client_name_t));
  55.  
  56. /*
  57.  * Graphics state storage management is complicated.  There are many
  58.  * different classes of storage associated with a graphics state:
  59.  *
  60.  * (1) The gstate object itself.  This includes some objects physically
  61.  *    embedded within the gstate object, but because of garbage collection
  62.  *    requirements, there are no embedded objects that can be
  63.  *    referenced by non-transient pointers.  We assume that the gstate
  64.  *    stack "owns" its gstates and that we can free the top gstate when
  65.  *    doing a restore.
  66.  *
  67.  * (2) Objects that are referenced directly by the gstate and whose lifetime
  68.  *    is independent of the gstate.  These are garbage collected, not
  69.  *    reference counted, so we don't need to do anything special with them
  70.  *    when manipulating gstates.  Currently this includes:
  71.  *        font, device
  72.  *
  73.  * (3) Objects that are referenced directly by the gstate, may be shared
  74.  *    among gstates, and should disappear when no gstates reference them.
  75.  *    We use reference counting to manage these.  Currently these are:
  76.  *        halftone, dev_ht, cie_render, black_generation,
  77.  *        undercolor_removal, set_transfer.*, cie_joint_caches
  78.  *    effective_transfer.* may point to some of the same objects as
  79.  *    set_transfer.*, but don't contribute to the reference count.
  80.  *    Similarly, dev_color may point to the dev_ht object.  For
  81.  *    simplicity, we initialize all of these pointers to 0 and then
  82.  *    allocate the object itself when needed.
  83.  *
  84.  * (4) Objects that are referenced directly by exactly one gstate and that
  85.  *    are not referenced (except transiently) from any other object.
  86.  *    These fall into three groups:
  87.  *
  88.  *   (4a) Objects lumped a single gs_state_contents object in order to
  89.  *    reduce the load on the allocator for gsave and grestore.  Each
  90.  *    gs_gstate_contents is referenced by exactly one gstate, and nowhere
  91.  *    else.  We reference the individual members through pointers, just as
  92.  *    though they were allocated individually, so that we wouldn't have to
  93.  *    keep remembering to put & in front of references to its components,
  94.  *    which would otherwise have to be embedded in the gstate object.
  95.  *    Again, we do not allow non-transient references to the objects
  96.  *    embedded in this object, aside from a single pointer from the gstate
  97.  *    object to each embedded component.  Currently these are:
  98.  *        path, clip_path, ccolor, dev_color
  99.  *
  100.  *   (4b) Objects allocated individually:
  101.  *        line_params.dash.pattern, color_space
  102.  *    color_space is a special case because it is referenced both
  103.  *    directly and also indirectly from image enumerators.
  104.  *    line_params.dash.pattern is also a special case, because it is
  105.  *    variable-length.  Otherwise, we could include these elements in
  106.  *    the contents object (4a).
  107.  *
  108.  *   (4c) The "client data" for a gstate.  For the interpreter, this is
  109.  *    the refs associated with the gstate, such as the screen procedures.
  110.  *    Client-supplied procedures manage client data.
  111.  *
  112.  * (5) Objects referenced indirectly from gstate objects of category (4),
  113.  *    including objects that may also be referenced directly by the gstate.
  114.  *    The individual routines that manipulate these are responsible
  115.  *    for doing the right kind of reference counting or whatever.
  116.  *    Currently:
  117.  *        path and clip_path require gx_path_share/release,
  118.  *          which use a 1-bit reference count;
  119.  *        color_space and ccolor require cs_adjust_color/cspace_count
  120.  *          or cs_adjust_counts, which use a full reference count;
  121.  *        dev_color has no references to storage that it owns.
  122.  *    We count on garbage collection or restore to deallocate
  123.  *      sub-objects of halftone.
  124.  *
  125.  * This situation is unnecessarily complicated.  We should get rid of
  126.  * the contents object and use reference counting to manage individually
  127.  * the objects it currently contains.  We should use full reference
  128.  * counting for paths, and use the freeing procedure to release the
  129.  * individual path elements.  However, making these changes runs a large
  130.  * risk of introducing hard-to-find bugs, so we don't plan to make them
  131.  * in the foreseeable future.
  132.  *
  133.  * Note that when we do a gsave, the newly allocated gstate doesn't
  134.  * necessarily reference the related objects that we allocate at the same
  135.  * time; in particular, the old contents go with the new gstate object and
  136.  * vice versa.  The same is true of grestore.  However, when we allocate
  137.  * gstates off-stack, the newly allocated gstate does reference the newly
  138.  * allocated component objects.  Note also that setgstate / currentgstate
  139.  * may produce gstates in which different allocators own different
  140.  * sub-objects; this is OK, because restore guarantees that there won't
  141.  * be any dangling pointers (as long as we don't allow pointers from
  142.  * global gstates to local objects).
  143.  */
  144.  
  145. /* The structure for allocating (most of) the contents of a gstate */
  146. /* all at once.  The typedef is in gzstate.c. */
  147. struct gs_state_contents_s {
  148.     gx_path path;
  149.     gx_clip_path clip_path;
  150.     gs_client_color ccolor;
  151.     gx_device_color dev_color;
  152. };
  153.  
  154. /* Enumerate the pointers in a graphics state, other than the ones */
  155. /* that point to the gs_state_contents and the ones in the imager state. */
  156. #define gs_state_do_ptrs(m)\
  157.   m(0,saved) m(1,contents)\
  158.   /*m(---,path)*/ /*m(---,clip_path)*/\
  159.   m(2,color_space)\
  160.   /*m(---,client_color)*/ /*m(---,dev_color)*/\
  161.   m(3,font) m(4,root_font) m(5,show_gstate) /*m(---,device)*/\
  162.   m(6,client_data)
  163. #define gs_state_num_ptrs 7
  164. /* Enumerate the pointers to the gs_state_contents. */
  165. #define gs_state_do_contents_ptrs(m)\
  166.   m(0,path) m(1,clip_path) m(2,ccolor) m(3,dev_color)
  167.  
  168. /* GC descriptors */
  169. private_st_line_params();
  170. private_st_imager_state();
  171. private_st_gs_state();
  172.  
  173. /* GC procedures for gs_imager_state */
  174. #define pis ((gs_imager_state *)vptr)
  175. private ENUM_PTRS_BEGIN(imager_state_enum_ptrs) ENUM_SUPER(gs_imager_state, st_line_params, line_params, st_imager_state_num_ptrs - st_line_params_num_ptrs);
  176. #define e1(i,elt) ENUM_PTR(i,gs_imager_state,elt);
  177.     gs_cr_state_do_ptrs(e1)
  178. #undef e1
  179. ENUM_PTRS_END
  180. private RELOC_PTRS_BEGIN(imager_state_reloc_ptrs) {
  181.     RELOC_SUPER(gs_imager_state, st_line_params, line_params);
  182. #define r1(i,elt) RELOC_PTR(gs_imager_state,elt);
  183.     gs_cr_state_do_ptrs(r1)
  184. #undef r1
  185. } RELOC_PTRS_END
  186. #undef pis
  187.  
  188. /* Components of the graphics state */
  189. gs_private_st_composite(st_gs_state_contents, gs_state_contents,
  190.   "gs_state_contents", state_contents_enum_ptrs, state_contents_reloc_ptrs);
  191. public_st_transfer_map();
  192.  
  193. /* GC procedures for gs_state */
  194. #define gsvptr ((gs_state *)vptr)
  195. private ENUM_PTRS_BEGIN(gs_state_enum_ptrs) ENUM_PREFIX(st_imager_state, gs_state_num_ptrs + 1);
  196. #define e1(i,elt) ENUM_PTR(i,gs_state,elt);
  197.     gs_state_do_ptrs(e1)
  198.     case gs_state_num_ptrs:        /* handle device specially */
  199.       ENUM_RETURN(gx_device_enum_ptr(gsvptr->device));
  200. #undef e1
  201. ENUM_PTRS_END
  202. private RELOC_PTRS_BEGIN(gs_state_reloc_ptrs) {
  203.     RELOC_PREFIX(st_imager_state);
  204.     { /* Save the contents pointer before relocation. */
  205.       byte *cont = (byte *)gsvptr->contents;
  206.       long reloc;
  207. #define r1(i,elt) RELOC_PTR(gs_state,elt);
  208.       gs_state_do_ptrs(r1)
  209. #undef r1
  210.       gsvptr->device = gx_device_reloc_ptr(gsvptr->device, gcst);
  211.       /* Now relocate the pointers into the contents. */
  212.       reloc = cont - (byte *)gsvptr->contents;
  213. #define r1(i,elt)\
  214.   gsvptr->elt = (void *)((byte *)gsvptr->elt - reloc);
  215.       gs_state_do_contents_ptrs(r1)
  216. #undef r1
  217.     }
  218. } RELOC_PTRS_END
  219. #undef gsvptr
  220.  
  221. /* GC procedures for gs_state_contents */
  222. #define cptr ((gs_state_contents *)vptr)
  223. private ENUM_PTRS_BEGIN_PROC(state_contents_enum_ptrs) {
  224.     gs_ptr_type_t ret;
  225. #define next_comp(np, st, e)\
  226.   if ( index < np ) { ret = (*st.enum_ptrs)(&cptr->e, sizeof(cptr->e), index, pep); goto rx; }\
  227.   index -= np
  228. #define last_comp(np, st, e)\
  229.   return (*st.enum_ptrs)(&cptr->e, sizeof(cptr->e), index, pep)
  230.     next_comp(st_path_max_ptrs, st_path, path);
  231.     next_comp(st_clip_path_max_ptrs, st_clip_path, clip_path);
  232.     next_comp(st_client_color_max_ptrs, st_client_color, ccolor);
  233.     last_comp(st_device_color_max_ptrs, st_device_color, dev_color);
  234. #undef next_comp
  235. #undef last_comp
  236. rx:    if ( ret == 0 )
  237.     {    /* A component ran out of pointers early. */
  238.         /* Just return a null so we can keep going. */
  239.         *pep = 0;
  240.         return ptr_struct_type;
  241.     }
  242.     return ret;
  243. ENUM_PTRS_END_PROC }
  244. private RELOC_PTRS_BEGIN(state_contents_reloc_ptrs) {
  245.     (*st_path.reloc_ptrs)(&cptr->path, sizeof(gx_path), gcst);
  246.     (*st_clip_path.reloc_ptrs)(&cptr->clip_path, sizeof(gx_clip_path), gcst);
  247.     (*st_client_color.reloc_ptrs)(&cptr->ccolor, sizeof(gs_client_color), gcst);
  248.     (*st_device_color.reloc_ptrs)(&cptr->dev_color, sizeof(gx_device_color), gcst);
  249. } RELOC_PTRS_END
  250. #undef cptr
  251.  
  252. /* Copy client data, using the copy_for procedure if available, */
  253. /* the copy procedure otherwise. */
  254. private int near
  255. gstate_copy_client_data(gs_state *pgs, void *dto, void *dfrom,
  256.   gs_state_copy_reason_t reason)
  257. {    return (pgs->client_procs.copy_for != 0 ?
  258.         (*pgs->client_procs.copy_for)(dto, dfrom, reason) :
  259.         (*pgs->client_procs.copy)(dto, dfrom));
  260. }
  261.  
  262. /* ------ Operations on the entire graphics state ------ */
  263.  
  264. /* Initialize an imager state, other than the parts covered by */
  265. /* gs_imager_state_initial. */
  266. /* The halftone, dev_ht, and ht_cache elements are not set or used. */
  267. private float
  268. null_transfer(floatp gray, const gx_transfer_map *pmap)
  269. {    return gray;
  270. }
  271. int
  272. gs_imager_state_initialize(gs_imager_state *pis, gs_memory_t *mem)
  273. {    pis->memory = mem;
  274.     /* Skip halftone */
  275.     { int i;
  276.       for ( i = 0; i < gs_color_select_count; ++i )
  277.         pis->screen_phase[i].x = pis->screen_phase[i].y = 0;
  278.     }
  279.     /* Skip dev_ht */
  280.     /* Skip ht_cache */
  281.     pis->cie_render = 0;
  282.     pis->black_generation = 0;
  283.     pis->undercolor_removal = 0;
  284.     /* Allocate an initial transfer map. */
  285.     rc_alloc_struct_n(pis->set_transfer.colored.gray,
  286.               gx_transfer_map, &st_transfer_map,
  287.               mem, return_error(gs_error_VMerror),
  288.               "gs_imager_state_init(transfer)", 4);
  289.     pis->set_transfer.colored.gray->proc = null_transfer;
  290.     pis->set_transfer.colored.gray->id = gs_next_ids(1);
  291.     pis->set_transfer.colored.gray->values[0] = frac_0;
  292.     pis->set_transfer.colored.red =
  293.       pis->set_transfer.colored.green =
  294.       pis->set_transfer.colored.blue =
  295.       pis->set_transfer.colored.gray;
  296.     pis->effective_transfer = pis->set_transfer;
  297.     pis->cie_joint_caches = 0;
  298.     pis->cmap_procs = cmap_procs_default;
  299.     pis->pattern_cache = 0;
  300.     return 0;
  301. }
  302.  
  303. /* Release an imager state. */
  304. void
  305. gs_imager_state_release(gs_imager_state *pis)
  306. {    static const char cname[] = "gs_imager_state_release";
  307. #define rcdecr(element)\
  308.   rc_decrement(pis->element, cname)
  309.  
  310.     rcdecr(cie_joint_caches);
  311.     rcdecr(set_transfer.colored.gray);
  312.     rcdecr(set_transfer.colored.blue);
  313.     rcdecr(set_transfer.colored.green);
  314.     rcdecr(set_transfer.colored.red);
  315.     rcdecr(undercolor_removal);
  316.     rcdecr(black_generation);
  317.     rcdecr(cie_render);
  318. #undef rcdecr
  319. }
  320.  
  321. /* Allocate and initialize a graphics state. */
  322. gs_state *
  323. gs_state_alloc(gs_memory_t *mem)
  324. {    gs_state *pgs = gstate_alloc(mem, "gs_state_alloc");
  325.  
  326.     if ( pgs == 0 )
  327.       return 0;
  328.     { static const gs_imager_state gstate_initial =
  329.         { gs_imager_state_initial(1.0) };
  330.       *(gs_imager_state *)pgs = gstate_initial;
  331.     }
  332.     /* Just enough of the state is initialized at this point */
  333.     /* that it's OK to call gs_state_free if an allocation fails. */
  334.     rc_alloc_struct_1(pgs->halftone, gs_halftone, &st_halftone, mem,
  335.               goto fail, "gs_state_alloc(halftone)");
  336.     pgs->saved = 0;
  337.     gstate_set_contents(pgs, pgs->contents);
  338.  
  339.     /* Initialize the color rendering state, except for elements */
  340.     /* which are in the gs_state contents (halftone). */
  341.  
  342.     pgs->halftone->type = ht_type_none;
  343.     pgs->dev_ht = 0;
  344.     pgs->ht_cache = gx_ht_alloc_cache(mem,
  345.                       gx_ht_cache_default_tiles(),
  346.                       gx_ht_cache_default_bits());
  347.     gs_imager_state_initialize((gs_imager_state *)pgs, mem);
  348.     pgs->client_data = 0;
  349.  
  350.     /* Initialize other things not covered by initgraphics */
  351.  
  352.     gx_path_init(pgs->path, mem);
  353.     gx_cpath_init(pgs->clip_path, mem);
  354.     /* Initialize things so that gx_remap_color won't crash. */
  355.     pgs->color_space->type = &gs_color_space_type_DeviceGray;
  356.     gx_set_device_color_1(pgs);
  357.     pgs->overprint = false;
  358.     gs_nulldevice(pgs);
  359.     gs_setalpha(pgs, 1.0);
  360.     gs_settransfer(pgs, null_transfer);
  361.     gs_setflat(pgs, 1.0);
  362.     gs_setfilladjust(pgs, 0.25, 0.25);
  363.     gs_setlimitclamp(pgs, false);
  364.     gs_setstrokeadjust(pgs, true);
  365.     pgs->font = 0;        /* Not right, but acceptable until the */
  366.                 /* PostScript code does the first setfont. */
  367.     pgs->root_font = 0;    /* ditto */
  368.     pgs->in_cachedevice = 0;
  369.     pgs->in_charpath = (gs_char_path_mode)0;
  370.     pgs->show_gstate = 0;
  371.     pgs->level = 0;
  372.     pgs->client_data = 0;
  373.     if ( gs_initgraphics(pgs) < 0 )
  374.        {    /* Something went very wrong */
  375.         return 0;
  376.        }
  377.     return pgs;
  378. fail:    gs_state_free(pgs);
  379.     return 0;
  380. }
  381.  
  382. /* Set the client data in a graphics state. */
  383. /* This should only be done to a newly created state. */
  384. void
  385. gs_state_set_client(gs_state *pgs, void *pdata,
  386.   const gs_state_client_procs *pprocs)
  387. {    pgs->client_data = pdata;
  388.     pgs->client_procs = *pprocs;
  389. }
  390.  
  391. /* Get the client data from a graphics state. */
  392. #undef gs_state_client_data        /* gzstate.h makes this a macro */
  393. void *
  394. gs_state_client_data(const gs_state *pgs)
  395. {    return pgs->client_data;
  396. }
  397.  
  398. /* Free a graphics state */
  399. int
  400. gs_state_free(gs_state *pgs)
  401. {    gstate_free_contents(pgs);
  402.     gs_free_object(pgs->memory, pgs, "gs_state_free");
  403.     return 0;
  404. }
  405.  
  406. /* Save the graphics state. */
  407. int
  408. gs_gsave(gs_state *pgs)
  409. {    gs_state *pnew = gstate_clone(pgs, pgs->memory, "gs_gsave",
  410.                       copy_for_gsave);
  411.  
  412.     if ( pnew == 0 )
  413.       return_error(gs_error_VMerror);
  414.     gx_path_share(pgs->path);
  415.     gx_cpath_share(pgs->clip_path);
  416.     pgs->saved = pnew;
  417.     if ( pgs->show_gstate == pgs )
  418.       pgs->show_gstate = pnew->show_gstate = pnew;
  419.     pgs->level++;
  420.     if_debug2('g', "[g]gsave -> 0x%lx, level = %d\n",
  421.           (ulong)pnew, pgs->level);
  422.     return 0;
  423. }
  424.  
  425. /* Restore the graphics state. */
  426. int
  427. gs_grestore(gs_state *pgs)
  428. {    gs_state *saved = pgs->saved;
  429.     void *pdata = pgs->client_data;
  430.     void *sdata;
  431.     if_debug2('g', "[g]grestore 0x%lx, level was %d\n",
  432.           (ulong)saved, pgs->level);
  433.     if ( !saved )        /* shouldn't happen */
  434.       return gs_gsave(pgs);
  435.     sdata = saved->client_data;
  436.     if ( saved->pattern_cache == 0 )
  437.       saved->pattern_cache = pgs->pattern_cache;
  438.     /* Swap back the client data pointers. */
  439.     pgs->client_data = sdata;
  440.     saved->client_data = pdata;
  441.     if ( pdata != 0 && sdata != 0 )
  442.       gstate_copy_client_data(pgs, pdata, sdata, copy_for_grestore);
  443.     gstate_free_contents(pgs);
  444.     *pgs = *saved;
  445.     if ( pgs->show_gstate == saved )
  446.       pgs->show_gstate = pgs;
  447.     gs_free_object(pgs->memory, saved, "gs_grestore");
  448.     if ( pgs->saved )
  449.       return 0;
  450.     return gs_gsave(pgs);
  451. }
  452.  
  453. /* Restore to the bottommost graphics state.  Also clear */
  454. /* the halftone caches, so stale pointers don't survive a restore. */
  455. int
  456. gs_grestoreall(gs_state *pgs)
  457. {    int code;
  458.     if ( !pgs->saved )        /* shouldn't happen */
  459.       return gs_gsave(pgs);
  460.     while ( pgs->saved->saved )
  461.     {    int code = gs_grestore(pgs);
  462.         if ( code < 0 )
  463.           return code;
  464.     }
  465.     code = gs_grestore(pgs);
  466.     if ( code < 0 )
  467.       return code;
  468.     gx_ht_clear_cache(pgs->ht_cache);
  469.     if ( pgs->pattern_cache )
  470.       (*pgs->pattern_cache->free_all)(pgs->pattern_cache);
  471.     return code;
  472. }
  473.  
  474. /* Allocate and return a new graphics state. */
  475. gs_state *
  476. gs_gstate(gs_state *pgs)
  477. {    return gs_state_copy(pgs, pgs->memory);
  478. }
  479. gs_state *
  480. gs_state_copy(gs_state *pgs, gs_memory_t *mem)
  481. {    gs_state *pnew;
  482.  
  483. #if 0 /****************/
  484.     if ( mem == pgs->memory )
  485. #endif /****************/
  486.       gstate_share_paths(pgs);
  487.     pnew = gstate_clone(pgs, mem, "gs_gstate", copy_for_gstate);
  488.     if ( pnew == 0 )
  489.       return 0;
  490.     pnew->saved = 0;
  491.     /*
  492.      * Prevent dangling references from the show_gstate pointer.  If
  493.      * this context is its own show_gstate, set the pointer in the clone
  494.      * to point to the clone; otherwise, set the pointer in the clone to
  495.      * 0, and let gs_setgstate fix it up.
  496.      */
  497.     pnew->show_gstate =
  498.       (pgs->show_gstate == pgs ? pnew : 0);
  499.     return pnew;
  500. }
  501.  
  502. /* Copy one previously allocated graphics state to another. */
  503. int
  504. gs_copygstate(gs_state *pto, const gs_state *pfrom)
  505. {    return gstate_copy(pto, pfrom, copy_for_copygstate, "gs_copygstate");
  506. }
  507.  
  508. /* Copy the current graphics state to a previously allocated one. */
  509. int
  510. gs_currentgstate(gs_state *pto, const gs_state *pgs)
  511. {    gstate_share_paths(pgs);
  512.     return gstate_copy(pto, pgs, copy_for_currentgstate, "gs_currentgstate");
  513. }
  514.  
  515. /* Restore the current graphics state from a previously allocated one. */
  516. int
  517. gs_setgstate(gs_state *pgs, const gs_state *pfrom)
  518. {    /*
  519.      * The implementation is the same as currentgstate,
  520.      * except we must preserve the saved pointer, the level,
  521.      * and possibly the show_gstate.
  522.      */
  523.     gs_state *saved_show = pgs->show_gstate;
  524.     int level = pgs->level;
  525.     int code = gstate_copy(pgs, pfrom, copy_for_setgstate, "gs_setgstate");
  526.  
  527.     if ( code < 0 )
  528.       return code;
  529.     pgs->level = level;
  530.     pgs->show_gstate =
  531.       (pgs->show_gstate == pfrom ? pgs : saved_show);
  532.     return 0;
  533. }
  534.  
  535. /* Get the allocator pointer of a graphics state. */
  536. /* This is provided only for the interpreter */
  537. /* and for color space implementation. */
  538. gs_memory_t *
  539. gs_state_memory(const gs_state *pgs)
  540. {    return pgs->memory;
  541. }
  542.  
  543. /* Get the saved pointer of the graphics state. */
  544. /* This is provided only for Level 2 grestore. */
  545. gs_state *
  546. gs_state_saved(const gs_state *pgs)
  547. {    return pgs->saved;
  548. }
  549.  
  550. /* Swap the saved pointer of the graphics state. */
  551. /* This is provided only for save/restore. */
  552. gs_state *
  553. gs_state_swap_saved(gs_state *pgs, gs_state *new_saved)
  554. {    gs_state *saved = pgs->saved;
  555.     pgs->saved = new_saved;
  556.     return saved;
  557. }
  558.  
  559. /* Swap the memory pointer of the graphics state. */
  560. /* This is provided only for the interpreter. */
  561. gs_memory_t *
  562. gs_state_swap_memory(gs_state *pgs, gs_memory_t *mem)
  563. {    gs_memory_t *memory = pgs->memory;
  564.     pgs->memory = mem;
  565.     return memory;
  566. }
  567.  
  568. /* ------ Operations on components ------ */
  569.  
  570. /* Reset most of the graphics state */
  571. int
  572. gs_initgraphics(gs_state *pgs)
  573. {    int code;
  574.     gs_initmatrix(pgs);
  575.     if (    (code = gs_newpath(pgs)) < 0 ||
  576.         (code = gs_initclip(pgs)) < 0 ||
  577.         (code = gs_setlinewidth(pgs, 1.0)) < 0 ||
  578.         (code = gs_setlinecap(pgs, gs_cap_butt)) < 0 ||
  579.         (code = gs_setlinejoin(pgs, gs_join_miter)) < 0 ||
  580.         (code = gs_setdash(pgs, (float *)0, 0, 0.0)) < 0 ||
  581.         (gs_setdashadapt(pgs, false),
  582.          (code = gs_setdotlength(pgs, 0.0, false))) < 0 ||
  583.         (code = gs_setgray(pgs, 0.0)) < 0 ||
  584.         (code = gs_setmiterlimit(pgs, 10.0)) < 0
  585.        )
  586.       return code;
  587.     gs_init_rop(pgs);
  588.     return 0;
  589. }
  590.  
  591. /* setfilladjust */
  592. int
  593. gs_setfilladjust(gs_state *pgs, floatp adjust_x, floatp adjust_y)
  594. {
  595. #define adjust_fill_adjust(v)\
  596.   if ( v < 0 ) v = 0; else if ( v > 0.5 ) v = 0.5
  597.     adjust_fill_adjust(adjust_x);
  598.     pgs->fill_adjust.x = float2fixed(adjust_x);
  599.     adjust_fill_adjust(adjust_y);
  600.     pgs->fill_adjust.y = float2fixed(adjust_y);
  601.     return 0;
  602. }
  603.  
  604. /* currentfilladjust */
  605. int
  606. gs_currentfilladjust(const gs_state *pgs, gs_point *adjust)
  607. {    adjust->x = fixed2float(pgs->fill_adjust.x);
  608.     adjust->y = fixed2float(pgs->fill_adjust.y);
  609.     return 0;
  610. }
  611.  
  612. /* setlimitclamp */
  613. void
  614. gs_setlimitclamp(gs_state *pgs, bool clamp)
  615. {    pgs->clamp_coordinates = clamp;
  616. }
  617.  
  618. /* currentlimitclamp */
  619. bool
  620. gs_currentlimitclamp(const gs_state *pgs)
  621. {    return pgs->clamp_coordinates;
  622. }
  623.  
  624. /* ------ Internal routines ------ */
  625.  
  626. /* Allocate a gstate and its contents. */
  627. private gs_state *
  628. gstate_alloc(gs_memory_t *mem, client_name_t cname)
  629. {    gs_state *pgs =
  630.       gs_alloc_struct(mem, gs_state, &st_gs_state, cname);
  631.     gs_state_contents *cont =
  632.       gs_alloc_struct(mem, gs_state_contents, &st_gs_state_contents, cname);
  633.     gs_color_space *pcs =
  634.       gs_alloc_struct(mem, gs_color_space, &st_color_space, cname);
  635.  
  636.     if ( pgs == 0 || cont == 0 || pcs == 0 )
  637.       {    gs_free_object(mem, pcs, cname);
  638.         gs_free_object(mem, cont, cname);
  639.         gs_free_object(mem, pgs, cname);
  640.         return 0;
  641.       }
  642.     pgs->line_params.dash.pattern = 0; /* in imager state */
  643.     pgs->memory = mem;
  644.     pgs->contents = cont;
  645.     pgs->color_space = pcs;
  646.     return pgs;
  647. }
  648.  
  649. /* Set the contents pointers of a gstate. */
  650. private void
  651. gstate_set_contents(gs_state *pgs, gs_state_contents *cont)
  652. {    pgs->contents = cont;
  653. #define gset(element)\
  654.   pgs->element = &cont->element;
  655.     gset(path);
  656.     gset(clip_path);
  657.     gset(ccolor);
  658.     gset(dev_color);
  659. #undef gset
  660. }
  661.  
  662. /* Copy the dash pattern from one gstate to another. */
  663. private int
  664. gstate_copy_dash(gs_state *pto, const gs_state *pfrom)
  665. {    return gs_setdash(pto, pfrom->line_params.dash.pattern,
  666.               pfrom->line_params.dash.pattern_size,
  667.               pfrom->line_params.dash.offset);
  668. }
  669.  
  670. /* Clone an existing graphics state. */
  671. /* Return 0 if the allocation fails. */
  672. /* The client is responsible for calling gx_[c]path_share on */
  673. /* whichever of the old and new paths is appropriate. */
  674. /* If for_gsave is true, the clone refers to the old contents, */
  675. /* and we switch the old state to refer to the new contents. */
  676. private gs_state *
  677. gstate_clone(gs_state *pfrom, gs_memory_t *mem, client_name_t cname,
  678.   gs_state_copy_reason_t reason)
  679. {    gs_state_contents *cfrom = pfrom->contents;
  680.     gs_color_space *csfrom = pfrom->color_space;
  681.     gs_state *pgs = gstate_alloc(mem, cname);
  682.     gs_state_contents *cont;
  683.     gs_color_space *pcs;
  684.  
  685.     if ( pgs == 0 )
  686.       return 0;
  687.     cont = pgs->contents;
  688.     pcs = pgs->color_space;
  689.     /* Increment references from gstate object. */
  690.     *pgs = *pfrom;
  691.     /* Copy the dash pattern if necessary. */
  692.     if ( pgs->line_params.dash.pattern )
  693.       { int code;
  694.         pgs->line_params.dash.pattern = 0; /* force allocation */
  695.         code = gstate_copy_dash(pgs, pfrom);
  696.         if ( code < 0 )
  697.           goto fail;
  698.       }
  699.     if ( pgs->client_data != 0 )
  700.     {    void *pdata = pgs->client_data =
  701.           (*pgs->client_procs.alloc)(mem);
  702.         if ( pdata == 0 ||
  703.              gstate_copy_client_data(pgs, pdata, pfrom->client_data, reason) < 0
  704.            )
  705.           goto fail;
  706.     }
  707.     rc_increment(pgs->set_transfer.colored.gray);
  708.     rc_increment(pgs->set_transfer.colored.red);
  709.     rc_increment(pgs->set_transfer.colored.green);
  710.     rc_increment(pgs->set_transfer.colored.blue);
  711.     rc_increment(pgs->halftone);
  712.     rc_increment(pgs->dev_ht);
  713.     rc_increment(pgs->cie_render);
  714.     rc_increment(pgs->black_generation);
  715.     rc_increment(pgs->undercolor_removal);
  716.     rc_increment(pgs->cie_joint_caches);
  717.     if ( reason == copy_for_gsave )
  718.       {    gstate_set_contents(pgs, cfrom);
  719.         pgs->color_space = csfrom;
  720.         gstate_set_contents(pfrom, cont);
  721.         pfrom->color_space = pcs;
  722.       }
  723.     else
  724.       {    gstate_set_contents(pgs, cont);
  725.         pgs->color_space = pcs;
  726.       }
  727.     *cont = *cfrom;
  728.     *pcs = *csfrom;
  729.     cs_adjust_counts(pgs, 1);
  730.     return pgs;
  731. fail:    gs_free_object(mem, pgs->line_params.dash.pattern, cname);
  732.     gs_free_object(mem, pcs, cname);
  733.     gs_free_object(mem, cont, cname);
  734.     gs_free_object(mem, pgs, cname);
  735.     return 0;
  736. }
  737.  
  738. /* Release the composite parts of a graphics state, */
  739. /* but not the state itself. */
  740. private void
  741. gstate_free_contents(gs_state *pgs)
  742. {    gs_memory_t *mem = pgs->memory;
  743.     static const char cname[] = "gstate_free_contents";
  744.     gx_device_halftone *pdht = pgs->dev_ht;
  745. #define rcdecr(element)\
  746.   rc_decrement(pgs->element, cname)
  747.  
  748.     gx_path_release(pgs->path);
  749.     gx_cpath_release(pgs->clip_path);
  750.     rcdecr(cie_joint_caches);
  751.     rcdecr(set_transfer.colored.gray);
  752.     rcdecr(set_transfer.colored.blue);
  753.     rcdecr(set_transfer.colored.green);
  754.     rcdecr(set_transfer.colored.red);
  755.     rcdecr(undercolor_removal);
  756.     rcdecr(black_generation);
  757.     rcdecr(cie_render);
  758.     if ( pdht != 0 && pdht->rc.ref_count == 1 )
  759.       { /* Make sure we don't leave dangling pointers in the cache. */
  760.         gx_ht_cache *pcache = pgs->ht_cache;
  761.  
  762.         if ( pcache->order.bits == pdht->order.bits ||
  763.          pcache->order.levels == pdht->order.levels
  764.            )
  765.           gx_ht_clear_cache(pcache);
  766.         gx_device_halftone_release(pdht, pdht->rc.memory);
  767.       }
  768.     rcdecr(dev_ht);
  769.     rcdecr(halftone);
  770.     cs_adjust_counts(pgs, -1);
  771.     if ( pgs->client_data != 0 )
  772.       (*pgs->client_procs.free)(pgs->client_data, mem);
  773.     gs_free_object(mem, pgs->line_params.dash.pattern, cname);
  774.     gs_free_object(mem, pgs->color_space, cname);
  775.     gs_free_object(mem, pgs->contents, cname);
  776. #undef rcdecr
  777. }
  778.  
  779. /*
  780.  * Mark both the old and new paths as shared when copying a gstate off-stack.
  781.  * If the old path was previously shared, we must search up
  782.  * the graphics state stack so we can mark its original ancestor
  783.  * as shared, because the off-stack copy defeats the one-bit
  784.  * reference count.
  785.  */
  786. private void
  787. gstate_share_paths(const gs_state *pgs)
  788. {    gx_path *ppath = pgs->path;
  789.     gx_clip_path *pcpath = pgs->clip_path;
  790.  
  791.     if ( ppath->shares_segments )
  792.       {    const gs_state *pcur;
  793.         const gs_state *prev;
  794.         const subpath *first;
  795.         for ( pcur = pgs, first = ppath->first_subpath;
  796.               (prev = pcur->saved) != 0 &&
  797.                 prev->path->first_subpath == first;
  798.               pcur = prev
  799.             )
  800.           if ( !prev->path->shares_segments )
  801.             {    gx_path_share(prev->path);
  802.             break;
  803.             }
  804.       }
  805.     else
  806.       gx_path_share(ppath);
  807.     /*
  808.      * If the clip path is a rectangle, free its path representation
  809.      * rather than copying it.
  810.      */
  811.     if ( pcpath->list.count <= 1 && pcpath->segments_valid )
  812.       { gx_path_release(&pcpath->path);
  813.         pcpath->segments_valid = false;
  814.       }
  815.     if ( pcpath->path.shares_segments )
  816.       {    const gs_state *pcur;
  817.         const gs_state *prev;
  818.         const subpath *first;
  819.         for ( pcur = pgs, first = pcpath->path.first_subpath;
  820.               (prev = pcur->saved) != 0 &&
  821.                 prev->clip_path->path.first_subpath == first;
  822.               pcur = prev
  823.             )
  824.           if ( !prev->clip_path->path.shares_segments )
  825.             {    gx_cpath_share(prev->clip_path);
  826.             break;
  827.             }
  828.       }
  829.     if ( pcpath->shares_list )
  830.       {    const gs_state *pcur;
  831.         const gs_state *prev;
  832.         const gx_clip_rect *head;
  833.         for ( pcur = pgs, head = pcpath->list.head;
  834.               (prev = pcur->saved) != 0 &&
  835.                 prev->clip_path->list.head == head;
  836.               pcur = prev
  837.             )
  838.           if ( !prev->clip_path->shares_list )
  839.             {    gx_cpath_share(prev->clip_path);
  840.             break;
  841.             }
  842.       }
  843.     gx_cpath_share(pcpath);
  844. }
  845.  
  846. /* Copy one gstate to another. */
  847. private int
  848. gstate_copy(gs_state *pto, const gs_state *pfrom,
  849.   gs_state_copy_reason_t reason, client_name_t cname)
  850. {    gs_state_contents *cto = pto->contents;
  851.     gs_color_space *csto = pto->color_space;
  852.  
  853.     /* Copy the dash pattern if necessary. */
  854.     if ( pfrom->line_params.dash.pattern || pto->line_params.dash.pattern )
  855.       { int code = gstate_copy_dash(pto, pfrom);
  856.         if ( code < 0 )
  857.           return 0;
  858.       }
  859.     /* It's OK to decrement the counts before incrementing them, */
  860.     /* because anything that is going to survive has a count of */
  861.     /* at least 2 (pto and somewhere else) initially. */
  862.     /* Handle references from contents. */
  863.     cs_adjust_counts(pto, -1);
  864.     gx_path_release(pto->path);
  865.     gx_cpath_release(pto->clip_path);
  866.     *cto = *pfrom->contents;
  867.     *csto = *pfrom->color_space;
  868.     cs_adjust_counts(pto, 1);
  869.     gx_path_share(pto->path);
  870.     gx_cpath_share(pto->clip_path);
  871.     /* Handle references from gstate object. */
  872. #define rccopy(element)\
  873.   rc_pre_assign(pto->element, pfrom->element, cname)
  874.     rccopy(cie_joint_caches);
  875.     rccopy(set_transfer.colored.gray);
  876.     rccopy(set_transfer.colored.blue);
  877.     rccopy(set_transfer.colored.green);
  878.     rccopy(set_transfer.colored.red);
  879.     rccopy(undercolor_removal);
  880.     rccopy(black_generation);
  881.     rccopy(cie_render);
  882.     rccopy(dev_ht);
  883.     rccopy(halftone);
  884. #undef rccopy
  885.     {    struct gx_pattern_cache_s *pcache = pto->pattern_cache;
  886.         void *pdata = pto->client_data;
  887.         gs_memory_t *mem = pto->memory;
  888.         gs_state *saved = pto->saved;
  889.         float *pattern = pto->line_params.dash.pattern;
  890.  
  891.         *pto = *pfrom;
  892.         pto->client_data = pdata;
  893.         pto->memory = mem;
  894.         pto->saved = saved;
  895.         pto->line_params.dash.pattern = pattern;
  896.         if ( pto->pattern_cache == 0 )
  897.           pto->pattern_cache = pcache;
  898.         if ( pfrom->client_data != 0 )
  899.           { /* We need to break 'const' here. */
  900.             gstate_copy_client_data((gs_state *)pfrom, pdata,
  901.                         pfrom->client_data, reason);
  902.           }
  903.     }
  904.     gstate_set_contents(pto, cto);
  905.     pto->color_space = csto;
  906.     pto->show_gstate =
  907.       (pfrom->show_gstate == pfrom ? pto : 0);
  908.     return 0;
  909. }
  910.